import turbogears           as tg
import cherrypy             as http
import commands
import socket
import md5
import time
import random
import os

from turbogears             import identity, url, flash, validators
from fasttrack.model        import (Person,Project, Risk, Note, Question, Answer,
                                    Issue, chance_codes, impact_codes,
                                    status_codes, ProjectFile)
from fasttrack.widgets      import (NoteWidget, RisksWidget, IssuesWidget, 
                                    QuestionWidget, AnswerWidget)
from datetime               import datetime
from fasttrack              import utils


class ProjectController(object):
    @tg.expose()
    @identity.require(identity.not_anonymous())
    def default(self, *args, **kwargs):
        parts = http.request.path.rsplit('/')
        if len(parts) == 3 and parts[-1].isdigit():
            return self.project(parts[-1])
    
    
    @tg.expose()
    @identity.require(identity.not_anonymous())
    def index(self, *args, **kwargs):
        project_id = self._active_project_id()
        if project_id:
            raise http.HTTPRedirect(url('/project/%s' % project_id))
        return self.locate()
    
    
    @tg.expose(template="fasttrack.templates.project.locate")
    @identity.require(identity.not_anonymous())
    def locate(self):
        all_projects = Project.select("parent_project_id is Null order by upper(name)")
        projects = [project for project in all_projects if not project.archived]
        
        return dict(active_section='project',
                    projects=projects)
    
    
    @tg.expose(template="fasttrack.templates.project.project")
    @tg.validate(validators=dict(project_id=validators.Int()))
    def project(self, project_id):
        project = Project.get(project_id)
        user_person = Person.get(identity.current.user.id)
        groupids = utils.getGroups()
        
        http.response.simpleCookie['active_project_id'] = project_id
        http.response.simpleCookie['active_project_id']['path'] = '/'
        
        people = Person.select(orderBy='displayName')
        
        return dict(active_section='project',
                    project=project,
                    chance_codes=chance_codes, 
                    impact_codes=impact_codes,
                    status_codes=status_codes,
                    show_closed_risks=bool(self._show_closed_risks()),
                    show_closed_issues=bool(self._show_closed_issues()),
                    show_all_notes=bool(self._show_all_notes()),
                    people=people,
                    user_person=user_person,
                    groupids=groupids)
    
    
    @tg.expose()
    def toggle_closed_risks(self):
        if self._show_closed_risks():
            http.response.simpleCookie['show_closed_risks'] = 0
        else:
            http.response.simpleCookie['show_closed_risks'] = 1
        http.response.simpleCookie['show_closed_risks']['path'] = '/'
        
        raise http.HTTPRedirect(url('/project/%s' % self._active_project_id()))
    
    
    @tg.expose()
    def toggle_closed_issues(self):
        if self._show_closed_issues():
            http.response.simpleCookie['show_closed_issues'] = 0
        else:
            http.response.simpleCookie['show_closed_issues'] = 1
        http.response.simpleCookie['show_closed_issues']['path'] = '/'
        
        raise http.HTTPRedirect(url('/project/%s' % self._active_project_id()))
    
    
    @tg.expose()
    def toggle_show_all_notes(self):
        if self._show_all_notes():
            http.response.simpleCookie['show_all_notes'] = 0
        else:
            http.response.simpleCookie['show_all_notes'] = 1
        http.response.simpleCookie['show_all_notes']['path'] = '/'
        
        raise http.HTTPRedirect(url('/project/%s' % self._active_project_id()))
    
    
    @tg.expose(fragment=True)
    @tg.validate(validators=dict(impact=validators.Int(), description=validators.String()))
    def create_issue(self, impact, description):
        creator = Person.get(identity.current.user.id)
        project = Project.get(self._active_project_id())
        
        issues = list(project.issues)
        
        issue = Issue(creator=creator, 
                      project=project, 
                      impact=impact,
                      issue=description)
        
        issues.append(issue)
        
        widget = IssuesWidget(issues=issues)
        
        return widget.render()
        
    
    @tg.expose(fragment=True)
    @tg.validate(validators=dict(impact=validators.Int(), chance=validators.Int(), description=validators.String()))
    def create_risk(self, impact, chance, description):
        creator = Person.get(identity.current.user.id)
        project = Project.get(self._active_project_id())
        
        risks = list(project.risks)
        
        risk = Risk(creator=creator, 
                    project=project, 
                    impact=impact, 
                    chance=chance, 
                    description=description)
        
        risks.append(risk)
        
        widget = RisksWidget(risks=risks)
        
        return widget.render()
    
    
    @tg.expose(fragment=True)
    @tg.validate(validators=dict(question=validators.String()))
    def create_question(self, question):
        creator = Person.get(identity.current.user.id)
        project = Project.get(self._active_project_id())
        
        new_question = Question(creator=creator,
                                project=project,
                                question=question)
        
        widget = QuestionWidget(question=new_question)
        return widget.render()
    
    
    @tg.expose(fragment=True)
    @tg.validate(validators=dict(question_id=validators.Int(), answer=validators.String()))
    def create_answer(self, question_id, answer):
        creator = Person.get(identity.current.user.id)
        question = Question.get(question_id)
        
        new_answer = Answer(creator=creator,
                            question=question,
                            answer=answer)
        
        widget = AnswerWidget(answer=new_answer)
        return widget.render()
    
    
    @tg.expose(fragment=True)
    @tg.validate(validators=dict(note=validators.String()))
    def create_note(self, note):
        creator = Person.get(identity.current.user.id)
        project = Project.get(self._active_project_id())
        
        note = Note(creator=creator, project=project, note=note)
        
        widget = NoteWidget(note=note)
        return widget.render()
    
    
    @tg.validate(validators=dict(note_id=validators.Int(), note=validators.String()))
    @tg.expose(fragment=True)
    def edit_note(self, note_id, note):
        n = Note.get(note_id)
        n.set(note=note, last_edit_date=datetime.now())
        widget = NoteWidget(note=n, include_container=False)
        return widget.render()
    
    
    @tg.expose()
    @tg.validate(validators=dict(note_id=validators.Int()))
    def remove_note(self, note_id):
        note = Note.get(note_id)
        Note.delete(note_id)
        return dict(success=True)
    
    
    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(note_id=validators.Int()))
    def get_note_content(self, note_id, **kwargs):
        note = Note.get(note_id)
        http.response.headerMap['Pragma'] = 'no-cache'
        http.response.headerMap['Cache-Control'] ='no-cache'
        http.response.headerMap['Expires'] = -1
        
        return dict(note=note.note)
    
    
    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(risk_id=validators.Int()))
    def close_risk(self, risk_id):
        risk = Risk.get(risk_id)
        risk.closed = True
        return dict(success=True)


    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(issue_id=validators.Int()))
    def close_issue(self, issue_id):
        issue = Issue.get(issue_id)
        issue.closed = True
        return dict(success=True)


    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(risk_id=validators.Int(), impact=validators.Int(), chance=validators.Int()))
    def modify_risk(self, risk_id, impact, chance):
        risk = Risk.get(risk_id)
        risk.set(impact=impact, chance=chance)
        return dict(success=True)
    
    
    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(question_id=validators.Int()))
    def remove_question(self, question_id):
        question = Question.get(question_id)

        for answer in question.answers:
            answer.destroySelf()

        question.destroySelf()

        return dict(success=True)


    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(answer_id=validators.Int()))
    def remove_answer(self, answer_id):
        answer = Answer.get(answer_id)
        answer.destroySelf()

        return dict(success=True)
        
    
    @tg.expose()
    def new_file(self, file):
        uploaddir = http.config.get('fasttrack.uploaddir')        
        try:
            if os.name == 'nt':
                filename = file.filename
                systemfilename = filename.split('.')[0] + self._uuid() + '.' + filename.split('.')[1]
                
            else:
                filename = file.filename
                systemfilename = filename.split('.')[0] + self._uuidgen() + '.' + filename.split('.')[1]
            f = open('%s%s' % (uploaddir, systemfilename), 'wb')
            while 1:
                data = file.file.read(1024*8)
                if not data:break
                f.write(data)
            f.close()
            
            creator = Person.get(http.request.identity.user.id)
            project = Project.get(self._active_project_id())
            
            ProjectFile(filename=filename, project=project, creator=creator, systemfilename=systemfilename)
        except:
            flash("Error creating file!")
        
        raise http.HTTPRedirect(url('/project/%s' % project.id))
        
    
    @tg.expose()
    @tg.validate(validators=dict(file_id=validators.Int()))
    def remove_file(self, file_id):
        uploaddir = http.config.get('fasttrack.uploaddir')
        file = ProjectFile.get(file_id)
        os.unlink('%s%s' % (uploaddir, file.systemfilename))
        ProjectFile.delete(file_id)
        
        raise http.HTTPRedirect(url('/project/%s' % file.project.id))
    
    
    @tg.expose()    
    @tg.validate(validators=dict(contact_id=validators.Int(), status=validators.Int()))
    def update_project(self, contact_id, status, description):
        contact = Person.get(contact_id)
        project = Project.get(self._active_project_id())
        project.set(status=int(status), contact=contact, description=description)
        
        raise http.HTTPRedirect(url('/project/%s' % project.id))
    
        
    @tg.expose(allow_json=True)
    @tg.validate(validators=dict(issue_id=validators.Int(), impact=validators.Int()))
    def modify_issue(self, issue_id, impact):
        issue = Issue.get(issue_id)
        issue.impact = impact
        return dict(success=True)
    
    
    @tg.expose()
    def archive_project(self):
        project = Project.get(self._active_project_id())
        project.archived = True
        
        raise http.HTTPRedirect(url('/project/%s' % project.id))
    
    
    @tg.expose()
    def unarchive_project(self):
        project = Project.get(self._active_project_id())
        project.archived = False
        
        raise http.HTTPRedirect(url('/project/%s' % project.id))
        
    
    def _uuidgen(self):
        return commands.getoutput('uuidgen')
    
    
    def _uuid(self):
        t = long(time.time() * 1000)
        r = long(random.random() * 100000000000000000L)
        try:
            a = socket.gethostbyname(socket.gethostname())
        except:
            # if we can't get a network address, just imagine one
            a = random.random() * 100000000000000000L
        data = str(t)+' '+str(r)+' '+str(a)
        data = md5.md5(data).hexdigest()
        return data
    
    def _active_project_id(self):
        if http.request.simpleCookie.has_key('active_project_id'):
            return int(http.request.simpleCookie['active_project_id'].value)
        return None
    
    def _show_closed_issues(self):
        if http.request.simpleCookie.has_key('show_closed_issues'):
            return int(http.request.simpleCookie['show_closed_issues'].value)
        return 0
    
    def _show_closed_risks(self):
        if http.request.simpleCookie.has_key('show_closed_risks'):
            return int(http.request.simpleCookie['show_closed_risks'].value)
        return 0

    def _show_all_notes(self):
        if http.request.simpleCookie.has_key('show_all_notes'):
            return int(http.request.simpleCookie['show_all_notes'].value)
        return 0